iT邦幫忙

2022 iThome 鐵人賽

DAY 30
1
Software Development

Kotlin on the way系列 第 30

Day 30 介面設計 Interface Design

  • 分享至 

  • xImage
  •  

在好想工作室 Web camp 的練習體裡面有這樣一題

細菌實驗中,原有 b隻細菌,每經過20分鐘細菌數量會增加為原來的2倍(2b),試寫一遞迴函數function twofold(b, m) 。讓使用者輸入分鐘數 m,並計算在沒有細菌死亡的狀況下,m 分鐘後的細菌有幾隻。
(細菌線性成長)

是為了讓學員了解函式的呼叫、遞迴的觀念等等,但我的情境和一般學員不同,我是已經會寫程式,想了解如何設計教學、題目的情況下去看到這題,我當下給出的解法是... 位移運算子!!XD

簡單講一下位移運算子,因為位元其實是 0 跟 1 (不是壞壞的 0 跟 1 )
2 -> 0010
4 -> 0100
8 -> 1000
可以看到,每往左邊一個就會乘二,阿記得小心溢位

所以我是先寫出這個寫法,也是無視了要求遞迴XD

function twoflod(b, m) {
    return b << (m/ 20)
}

那沒關係,遞迴不是這篇重點,現在來看看這個解法有什麼問題~

優點

  • 效率高到飛起來
  • 記憶體用量超低
  • 只花 20 秒查 js 位移運算子的寫法加上 10 秒

缺點

  • 在 Js 裡面,在整數最大值時會溢出,但 Number 可以到更大
  • 沒彈性,不同細菌種類可能會依照不同的速度成長

但其實以這個問題來說,我自己還是能給過,要真正防止數字溢出,唯一解就是用字串紀錄,並針對常見數學操作編寫轉換邏輯,否則沒給上下限範圍都有機會溢出
而沒彈性的缺點,是沒話說拉QQ,這是有擴展性跟過度設計的辯論

現在我們假設這題是在現實專案中呢,會發生什麼事?作為開發者,我們會提出幾個問題

  1. 會有不同細菌以不同時間速度增加嗎?
  2. 會有不同細菌以不同倍數增加嗎?
  3. 細菌不會自然死亡嗎?
  4. 細菌不會資源稀缺死亡嗎?
  5. 有預估最大值嗎?
  6. 有空間限制嗎?有空間的話有密度限制嗎?如果有密度限制,他會影響到該細菌分裂效率嗎?
    ...

如果你也能提出類似的問題,恭喜你,下去領500 有成為工程師的潛力

那問題可以改成

細菌實驗中,在 999 * 999 方格內,原有 b隻細菌從左上排列,每經過 x 分鐘細菌數量會增加為原來的times倍(timesb),細菌存活時間為 3x,如以細菌為中心,周圍的 8 格內超過 4 個細菌,該細菌死亡,試寫一函數function twofold(b, x, times , m) 。讓使用者輸入分鐘數 m,並計算 m 分鐘後的細菌有幾隻。
(細菌線性成長)

整理一下會變成

空間限制 999 * 999
原有 b 隻細菌從左上排列
每經過 x 分鐘細菌數量會增加為原來的times倍(timesb)
每 3x 分鐘細菌會自然死亡
如果細菌周遭超過 4 個細菌會資源稀缺死亡

b > 0
10 < times < 0
60 < x < 0
m < 1440

first try

第一次用 pseudocode 解題


class Bacteria {
    // position
    // id
    // naturalLifeTime
    // isAlive
    // nearByCacteria = listOf<Bacteria>
    // checkNearArea()
    // generateBacteria()
}

這樣的程式會有什麼問題呢?

作為單一細菌的類別,有著太多職責,一出生就知道自己的位置、id、死亡倒數以及是否死亡,同時他擁有鄰居狀態,且可以自行檢測,還能夠生成其他細菌並安排位置給他

常見錯誤

工程師的常見錯誤就是用全知角度去寫程式,因為我們以上帝視角看整個細菌實驗,在編寫細菌類別時,也會容易以上帝視角帶入,變成每個細菌都了解整個實驗的機制和狀態,另一方面,也會造成重複且不一致的資料

用用上帝視角設計程式,儘管程式可以執行,但隨著業務邏輯增加、新功能、舊功能維護等等,全知視角的設計會容易出事,更不用說對未來可預期的業務邏輯變化,比如不同的細菌生成速度、溫度、排序方式等等,盡可能在一開始就把設計做對做好,減少以後重構維護的成本

那正確的做法是什麼呢?
這次先把開發者自身帶入細菌,不妨問問自己

  1. 你會如何得知自己位置?
  2. 你是否知道自己何時死亡?
  3. 你應該對鄰居全盤了解嗎?
  4. 生成的新細菌要視做獨立個體還是有關係個體?

帶入 OOP 觀念的解法

既然已經知道職責太多,我們現在拉出一些職責,我們預計要有

  • 地理資訊類別
    • 提供單點地理資訊
    • 提供矩形區塊細菌 id
    • 提供空方格列表
  • 細菌資料類別
    • 可依據 id 搜尋
  • 計時類別
    • 呼叫殺手類別處理自然死亡細菌
    • 更新自然死亡細菌
  • 細菌生成類別
    • 生成新細菌,並從左上補缺依序排列
  • 細菌殺手類別
    • 處理自然死亡細菌
    • 殺死資源稀缺細菌
  • 細菌類別
    • id
    • isAlive

棒棒的,現在每個類別都找到自己的職責,可以看到,細菌類別本菌只需要擁有自己 id 和 isAlive 兩種資訊狀態,其他的職責邏輯都可以交給外部處理,更重要的事,每個細菌只會知道自己的狀態,須了解其他細菌或整個細菌實驗的狀態,而這樣的設計,也使系統可以適應不同細菌的變化的彈性

summary

其實這篇的主題,是物件導向的基本功,但也是我一直有收穫的主題,我每幾個月回顧都會有新收穫跟新想法,在此拋磚引玉,希望可以有大大分享更詳盡的心法

English

Question

In bacteria experiment, there are b amount bacteria, every 20 minute pass, will double the amount, try write a recursion function function twofold(b, m) allow user input m minutes, and calculate the amount of bacteria

This is design for practice function call, the concept of recursion, but I simple got the first solution with shift operator

The idea of shift operator is bit consist by 0 and 1, and we can move them
2 -> 0010
4 -> 0100
8 -> 1000
just like the sample, move to left equal to times two, just mind over flow

function twoflod(b, m) {
    return b << (m/ 20)
}

But what is the issue with this solution?

Pros

  • efficiency
  • low usage of memory
  • very quick to finish coding task

Cons

  • in javascript, integer will overflow when Number could be greater
  • Not flexible, different bacteria could grows in different speed

If this question is in real project, I will not deliver the code sample, as a developer, there are some questions we should concern

  1. Do different bacteria increase in different time ranges?
  2. Do different bacteria increase in different ratios?
  3. Do bacteria die naturally?
  4. Do bacteria die because of a lack of resources?
  5. Max limit?
  6. Space limit? density limit? Does density affect bacteria increase? ...

If you can ask question like this, congration

So the question could be

In bacteria experiment, inside square amount 999 * 999, amount b bacteria line up from left top, every m minute the amount will increase times times, the life time of bacteria is 3x, each bacteria will dies due to leak of resource when there are over 4 bacteria around it, try write a function function twofold allow user input …
So our limit will be
Space limit 999 * 999
b bacteria start from left top
every x minute times times amount
every 3x minutes the bacteria die naturally
died when over 4 bacteria stay around it

b > 0
10 < times < 0
60 < x < 0
m < 1440

first try

using pseudocode solve it


class Bacteria {
    // position
    // id
    // naturalLifeTime
    // isAlive
    // nearByCacteria = listOf<Bacteria>
    // checkNearArea()
    // generateBacteria()
}

What is the problem?

As a single bacteria, you have too much responsibility, it knows about its location, id, life time countdown and isAlive, meanwhile, it have the status of neighborhood, and capable to self check, and generate a new bacteria and arrange position

Common mistake

A common mistake as engineer is design program in god view, when we design bacteria class, we allow every bacteria knows all the experiment rule and state, on the other hands, there are redundancy data

So what should we do?
you can ask you self

  1. How do you know about your location
  2. Do you know about when will you die
  3. Do you know about everything in your neighborhood?
  4. Does any connection between new bacteria and its parent

Solution with OOP

Now we know about the responsibility, we can create more class for them

  • GeoData
    • data from xy position
    • bacteria ids of neighborhood
    • empty position
  • bacteria manager
    • search by id
  • count down class
    • call kill process for naturally die
    • update alive state
  • bacteria generator
    • generate new bacteria
  • bacteria killer
    • deal with nature pass away
    • kill bacteria lack of resource
  • bacteria class
    • id
    • isAlive

Great, now every class have its own responsibility, and bacteria own it id and isAlive state, other logic could handle by other class, more importantly, every bacteria knows it state, but know nothing about while experiment, this design allow the system suit different kind of bacteria

summary

The topic of this article, is the basic of oop, every few months I learn new concept and new thing on this topic


上一篇
Day 29 設計模式 依賴注入的細節
下一篇
小結 以及還沒講到的東西
系列文
Kotlin on the way31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言